<template>
  <div
    ref="rootElement"
    class="render-panel"
    @mousedown="handleMouseDown"
    @mousemove="handleMouseMove"
    @mouseup="handleMouseUp"
  >
    <render-layout ref="renderElement" />
    <render-sprite ref="spriteElement" />
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import renderSprite from './renderSprite.vue'
import renderLayout from './renderLayout.vue'
import { SpriteRoot } from './renderStore'
// 值更新后只刷新对应图层，而不是全局重新渲染
// 用户操作类图层使用svg或者dom元素，角色渲染和动画效果使用画布

defineOptions({
  name: 'render-layout'
})

const $emit = defineEmits(['mousedown', 'mousemove', 'mouseup'])

const rootElement = ref<HTMLDivElement | null>(null)

const contentElement = ref<HTMLDivElement | null>(null)

const spriteElement = ref<InstanceType<typeof renderSprite> | null>(null)

const store = ref<SpriteRoot>()

// 以整个屏幕做基本宽高
const actualWidth = ref(window['designWidth'])
const actualHeight = ref(window['designHeight'])

onMounted(() => {
  store.value = new SpriteRoot({
    screen: rootElement.value,
    panel: contentElement.value,
    sprite: spriteElement.value,
    designWidth: actualWidth.value,
    designHeight: actualHeight.value
  })
})

const config = (value: any, state: any) => store.value?.init(value, state)

const setState = (state: any, option?: any) => store.value?.setState(state, option)

const getState = () => store.value?.state

const canvasRender = () => store.value?.render()

const updateFrame = () => store.value?.updateFrame()

const handleMouseDispatch = (mouseAction: 'mousedown' | 'mousemove' | 'mouseup') => {
  return (event: MouseEvent) => {
    const rect = rootElement.value?.getBoundingClientRect()
    if (rect) {
      const widthScale = actualWidth.value / rect.width
      const heightScale = actualHeight.value / rect.height
      const x = Math.round((event.clientX - rect.left) * widthScale)
      const y = Math.round((event.clientY - rect.top) * heightScale)
      const point: any = { x, y }
      point['listen'] = store.value?.nodeListen(point)
      $emit(mouseAction, point)
    }
  }
}

const handleMouseDown = handleMouseDispatch('mousedown')

const handleMouseMove = handleMouseDispatch('mousemove')

const handleMouseUp = handleMouseDispatch('mouseup')

defineExpose({
  config,
  setState,
  getState,
  canvasRender,
  updateFrame
})
</script>

<style lang="scss">
.render-panel {
  width: 100%;
  height: 100%;
  font-size: 0;
  .render-content {
    width: 100%;
    height: 100%;
  }
  .sprite-node {
    display: inline-block;
    position: absolute;
    left: 0;
    top: 0;
    z-index: 0;
    canvas {
      display: inline-block;
      position: absolute;
      left: 0;
      top: 0;
    }
  }
}
</style>
